﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;

public class RotateSpinner : MonoBehaviour {

	public static bool canRotate = true;
	bool startRotate = false;
	bool currentlyRotating = false;
	Vector3 startPosition = Vector3.zero;
	Vector3 initialPositionForRelease = Vector3.zero;
	Vector3 endPosition = Vector3.zero;

	Vector3 startPosition2 = Vector3.zero;
	Vector3 endPosition2 = Vector3.zero;

	Vector3 difference = Vector3.zero;
	float startTime = 0;
	int previousRotationDirection = 0;
	int rotationDirection = 0; // 0: not spinning, -1: spin to left, 1: spin to right
	float rotationPower = 0;
	float countingTimer;

	// VARIABLES START
	float friction = 0.997f;
	float rotationPowerLimit = 500;
	float powerFactor = 20f;
	float maxTimeInterval = 0.35f;
	int scoreFactor = 50;
	float minMagnitudeForSpin = 0.2f;
	float timerInSeconds = 25;
	float velocityLimit = 4000;
	int scoreLimitMax = 250;
	int scoreLimitMin = 120;
	int coinsLimitMin = 10;
	int coinsLimitMax = 20;
	// VARIABLES END

	Vector3 crossProduct;
	Vector3 normalizedCrossProduct;
	public Text scoreText;
	int score = 0;
	public Text coinsText;
	int coins = 0;
	public Text timerText;
	public Text hiScoreText;
	int coinsAtTheBeginningOfScene = 0;
	public static bool timerMode = false;
	bool initiateTimer = false;
	bool swing = false;
	float totalPower;
	Rigidbody2D Rigidbody2D;
	Rigidbody2D Rigidbody2Dshadow;
	bool coroutineStarted = false;
	float previousAngle = -5000;
	float currentAngle = 0;
	int oldCoins;
	int randomScore = 0;
	int randomCoins = 0;
	int tempScore = 0;
	public GameObject ButtonEnd;
	float initialSpin = 0;
	public GameObject ButtonPause;
	public GameObject ButtonShop;
	public Transform coinsAnimation;
	public Transform coinsDestinationTarget;
	GameObject previousMenu;
	Transform imageShadow;
	Animator plusCoinsAnimator;
	public Color highscoreColor;
	bool highscoreSet = false;

	public GameObject pausePopupForApplicationPause;

	static RotateSpinner instance;
	public static RotateSpinner Instance
	{
		get
		{
			if(instance == null)
			{
				instance = GameObject.FindObjectOfType(typeof(RotateSpinner)) as RotateSpinner;
			}

			return instance;
		}
	}

	void Start () 
	{
		canRotate = true;
		Input.multiTouchEnabled = false;
		countingTimer = timerInSeconds;
		Rigidbody2D = GetComponent<Rigidbody2D>();

		if(PlayerPrefs.HasKey("TotalCoins"))
		{
			GlobalVariables.totalCoins = PlayerPrefs.GetInt("TotalCoins");
		}

		coinsAtTheBeginningOfScene = GlobalVariables.totalCoins;
		coinsText.text = GlobalVariables.totalCoins.ToString();

		if(PlayerPrefs.HasKey("HiScore"))
		{
			GlobalVariables.hiScore = PlayerPrefs.GetInt("HiScore");
		}
		hiScoreText.text = GlobalVariables.hiScore.ToString();
		scoreText.text = "0";

		ButtonPause.gameObject.SetActive(false);

		if(timerMode)
		{
			timerText.text = timerInSeconds.ToString("F");
			timerText.transform.parent.gameObject.SetActive(true);
		}
		imageShadow = transform.parent.Find("ImageShadow");
		Rigidbody2Dshadow = imageShadow.GetComponent<Rigidbody2D>();

		Shop.Instance.SetEquippedItem(GetComponent<Image>());

		randomScore = Random.Range(scoreLimitMin,scoreLimitMax);
		randomCoins = Random.Range(coinsLimitMin,coinsLimitMax);
		plusCoinsAnimator = coinsText.transform.parent.Find("+CoinsHolder/AnimationHolder").GetComponent<Animator>();
	}

	void StopBoost()
	{
		startRotate = false;
	}

	void Update () 
	{
		if(timerMode && initiateTimer)
		{
			countingTimer -= Time.deltaTime;

			if(countingTimer < 0) 
				countingTimer = 0;
			
			timerText.text = countingTimer.ToString("F");
			//Debug.Log("TIMER: " + countingTimer);
			if(countingTimer <= 0) 
			{
				initiateTimer = false;
				ButtonEndClicked(MenuManager.Instance.transform.Find("PopUps/PopUpGameOver").gameObject);
			}
		}

		if(canRotate)
		{
			currentAngle = transform.rotation.eulerAngles.z;
			if(!coroutineStarted && startRotate)
				StartCoroutine(StartCountingPoints());
			if(UnityEngine.EventSystems.EventSystem.current.currentSelectedGameObject == null)
			{
				if(Input.GetMouseButtonDown(0))
				{
					startRotate = true;
					startPosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
					startPosition2 = initialPositionForRelease = startPosition = new Vector3(startPosition.x, startPosition.y, 0);
					endPosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
					endPosition2 = endPosition = new Vector3(endPosition.x, endPosition.y, 0);
					startTime = Time.time;
					if(initialSpin == 0)
					{
						initialSpin = Time.time;
						ButtonShop.gameObject.SetActive(false);
						ButtonPause.gameObject.SetActive(true);
						transform.parent.Find("HandHolder").gameObject.SetActive(false);
					}
					swing = false;

					if(timerMode && !initiateTimer)
						initiateTimer = true;

					StartCoroutine("CheckDifference");
				}
				else if(Input.GetMouseButton(0))
				{
					endPosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
					endPosition2 = endPosition = new Vector3(endPosition.x, endPosition.y, 0);
					crossProduct = Vector3.Cross(startPosition,endPosition);
					normalizedCrossProduct = crossProduct.normalized;

					if(normalizedCrossProduct.z < 0)
						rotationDirection = -1;
					else if(normalizedCrossProduct.z > 0)
						rotationDirection = 1;
					else
						rotationDirection = 0;
					currentlyRotating = true;
					startPosition = endPosition;
					difference = endPosition2 - startPosition2;
					rotationPower = difference.magnitude*2.25f;
					//rotationPower = difference.magnitude;
				}
				else if(Input.GetMouseButtonUp(0))
				{
					StopCoroutine("CheckDifference");
					if(Time.time - startTime <= maxTimeInterval)
					{
						endPosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
						endPosition = new Vector3(endPosition.x, endPosition.y, 0);
						crossProduct = Vector3.Cross(initialPositionForRelease,endPosition);
						normalizedCrossProduct = crossProduct.normalized;
						difference = endPosition - initialPositionForRelease;

						if(normalizedCrossProduct.z < 0)
							rotationDirection = -1;
						else if(normalizedCrossProduct.z > 0)
							rotationDirection = 1;

						if(previousRotationDirection != 0)
						{
							if(previousRotationDirection != rotationDirection)
							{
								if(difference.magnitude > 0.15f && (Time.time - startTime) > 0)
									rotationPower = (difference.magnitude*2.25f/((Time.time - startTime)))/4.5f;//difference.magnitude/((Time.time - startTime))*10;
							}
							else
							{
								if(difference.magnitude > 0.15f && (Time.time - startTime) > 0)
									rotationPower = difference.magnitude*2.25f/((Time.time - startTime));//difference.magnitude/((Time.time - startTime))*10;
							}
						}
						else
						{
							if(difference.magnitude > 0.15f && (Time.time - startTime) > 0)
								rotationPower = difference.magnitude*2.25f/((Time.time - startTime));//difference.magnitude/((Time.time - startTime))*10;
						}

						previousRotationDirection = rotationDirection;


						swing = true;
					}
				}								
			}
		}
	}

	void FixedUpdate()
	{
		if(currentlyRotating || swing)
		{
			totalPower = rotationPower * rotationDirection * powerFactor;
			totalPower = Mathf.Clamp(totalPower, -velocityLimit, velocityLimit);
			Rigidbody2D.AddTorque(totalPower, ForceMode2D.Force);
			Rigidbody2Dshadow.AddTorque(totalPower, ForceMode2D.Force);
			currentlyRotating = false;
			swing = false;
		}
		Rigidbody2D.angularVelocity = Mathf.Clamp(Rigidbody2D.angularVelocity, -velocityLimit, velocityLimit);
		Rigidbody2Dshadow.angularVelocity = Mathf.Clamp(Rigidbody2D.angularVelocity, -velocityLimit, velocityLimit);
		if(Rigidbody2D.angularVelocity < 0.2f && Rigidbody2D.angularVelocity > -0.2f && startRotate && (Time.time - initialSpin) > 3f && !timerMode) 
		{
			ButtonEndClicked(MenuManager.Instance.transform.Find("PopUps/PopUpGameOver").gameObject);
		}
		else if(Rigidbody2D.angularVelocity < 10 && Rigidbody2D.angularVelocity > -10) 
		{
			previousRotationDirection = 0;
		}
		else
		{
			if(Rigidbody2D.angularVelocity < 30 && Rigidbody2D.angularVelocity > -30) 
			{
				if(!ButtonEnd.activeSelf && startRotate && (Time.time - initialSpin) > 3f)
				{
					ButtonEnd.SetActive(true);
				}
			}
			else
			{
				if(ButtonEnd.activeSelf)
				{
					ButtonEnd.SetActive(false);
				}
			}
		}
	}

	IEnumerator CheckDifference()
	{
		yield return new WaitForSeconds(0.1f);
		startPosition2 = endPosition2;
		StartCoroutine("CheckDifference");
	}


	IEnumerator StartCountingPoints()
	{
		coroutineStarted = true;
		if(previousAngle != -5000)
		{
			if(Mathf.Abs(previousAngle - currentAngle) > 75f && canRotate)
			{
				score += Mathf.CeilToInt(Mathf.Abs(previousAngle - currentAngle)/75f);
				tempScore += Mathf.CeilToInt(Mathf.Abs(previousAngle - currentAngle)/75f);
				scoreText.text = score.ToString();
				if(tempScore > randomScore)
				{
					//coins = (int)(tempScore/(float)randomScore);
					coins += randomCoins;
					plusCoinsAnimator.transform.GetChild(2).GetComponent<Text>().text = "+" + randomCoins;
					randomCoins = Random.Range(coinsLimitMin,coinsLimitMax);
					tempScore = 0;
					GlobalVariables.totalCoins = coinsAtTheBeginningOfScene + coins;
					Invoke("PlusAnimationAndSetText",0.7f);
					randomScore = Random.Range(scoreLimitMin,scoreLimitMax);
					SoundManager.Instance.Play_CoinCollected();
					StartCoroutine(MoveCoinsAnimationHolder());
				}

				if(GlobalVariables.hiScore < score)
				{
					if(!highscoreSet)
						highscoreSet = true;
					GlobalVariables.hiScore = score;
					hiScoreText.text = GlobalVariables.hiScore.ToString();
					hiScoreText.color = highscoreColor;
				}
			}
		}
		previousAngle = currentAngle;
		//yield return new WaitForSeconds(0.075f);
		yield return new WaitForSeconds(0.02f);
		StartCoroutine(StartCountingPoints());
	}

	IEnumerator MoveCoinsAnimationHolder()
	{
		coinsAnimation.position = transform.position;
		coinsAnimation.GetChild(0).GetComponent<Animator>().Play("CoinsDrop",0,0);
		while(coinsDestinationTarget.position.y - coinsAnimation.position.y > 0.1f)
		{
			coinsAnimation.position = Vector3.MoveTowards(coinsAnimation.position,coinsDestinationTarget.position,Time.deltaTime*4.3f);
			yield return null;
		}
	}

	void PlusAnimationAndSetText()
	{
		plusCoinsAnimator.Play("+Coins",0,0);
		coinsText.text = GlobalVariables.totalCoins.ToString();
	}

	void AddScore(int amount)
	{
		score += amount;
		scoreText.text = score.ToString();
	}

	public void ButtonEndClicked(GameObject menu)
	{
		if(canRotate)
		{
			canRotate = false;
			menu.transform.Find("AnimationHolder/Body/ContentHolder/TextBGScore/ScoreResult").GetComponent<Text>().text = scoreText.text = score.ToString();
			menu.transform.Find("AnimationHolder/Body/ContentHolder/TextBGHiScore/HiScoreResult").GetComponent<Text>().text = GlobalVariables.hiScore.ToString();
			if(highscoreSet)
				menu.transform.Find("AnimationHolder/Body/ContentHolder/TextBGHiScore/HiScoreResult").GetComponent<Text>().color = highscoreColor;
			PlayerPrefs.SetInt("TotalCoins",GlobalVariables.totalCoins);
			PlayerPrefs.SetInt("HiScore",GlobalVariables.hiScore);
			PlayerPrefs.Save();
			MenuManager.Instance.ShowPopUpMenu(menu);
		}
	}

	public void ButtonTryAgainClicked()
	{
		if(timerMode)
			GlobalVariables.FlurryEvent("Game Mode Events","Game Mode Started","Timed Spin");
		else
			GlobalVariables.FlurryEvent("Game Mode Events","Game Mode Started","Free Spin");
		//SceneManager.LoadScene("GamePlay");
		Invoke("LoadGameplaySceneWithDelay",1f);
		SoundManager.Instance.Play_ButtonClick();
		//WebelinxCMS.Instance.ShowInterstitial(4);
		if(Transition.allowTransition)
		{
			Transition.canPlayInterstitial = true;
			Transition.Instance.PlayTransition();
		}
	}

	void LoadGameplaySceneWithDelay()
	{
		SceneManager.LoadScene("GamePlay");
	}

	void LoadMainSceneWithDelay()
	{
		SceneManager.LoadScene("MainScene");
	}

	public void PauseGame(GameObject menu)
	{
		Time.timeScale = 0;
		MenuManager.Instance.ShowPopUpMenu(menu);
	}

	public void ResumeGame(GameObject menu)
	{
		MenuManager.Instance.ClosePopUpMenu(menu);
		Time.timeScale = 1;
	}

	public void OpenMenu(GameObject menu)
	{
		canRotate = false;
		previousMenu = MenuManager.Instance.currentMenu.gameObject;
		MenuManager.Instance.ShowMenu(menu);
	}

	public void CloseMenu(GameObject menu)
	{
		MenuManager.Instance.CloseMenu(menu);
		MenuManager.Instance.ShowMenu(previousMenu);
		canRotate = true;
		coinsText.text = GlobalVariables.totalCoins.ToString();
		coinsAtTheBeginningOfScene = GlobalVariables.totalCoins;
	}

	public void BackToMenu()
	{
		//SceneManager.LoadScene("MainScene");
		Time.timeScale = 1;
		Invoke("LoadMainSceneWithDelay",1f);
		//WebelinxCMS.Instance.ShowInterstitial(4);
		if(Transition.allowTransition)
		{
			Transition.canPlayInterstitial = true;
			Transition.Instance.PlayTransition();
		}
	}

	void OnApplicationPause(bool status)
	{
		if(status)
		{
			if(Time.timeScale == 1 && ButtonPause.gameObject.activeSelf && canRotate) // not already paused, not on start state before beginning to rotate, and not on game over
			{
				PauseGame(pausePopupForApplicationPause);
			}
		}
	}
}
